home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * canbrush -
- * Draw a brush onto the canvas.
- *
- * Paul Haeberli - 1991
- *
- * exports
- *
- void drawbrush(dest,fx,fy)
- void getcircpos(x,y);
- float qrand();
- int getqrandstate();
- int setqrandstate(s);
- setcurwidth(w);
- *
- */
- #include "values.h"
- #include "math.h"
- #include "stdio.h"
- #include "canvas.h"
-
- extern float can_curalpha;
- extern float can_curalphascale;
-
- #define RANDTABSIZE (2*1020)
-
- float frand();
- static freebrush();
- static brush *makebrush();
-
- static brush *curbrush;
- static float curwidth;
- static float curbwidth, curbalpha;
- static float *circpos;
- static float *randtab;
- static float randfirsted;
- static int qp;
-
- /*
- * draw brushes
- *
- */
- static updatebrush(width,alpha)
- float width, alpha;
- {
- if (width != curbwidth || alpha != curbalpha) {
- if (curbrush)
- freebrush(curbrush);
- curbrush = makebrush(width,width,alpha);
- curbwidth = width;
- curbalpha = alpha;
- }
- }
-
- static float brushfunc(xpos,ypos)
- float xpos, ypos;
- {
- float rad, val;
-
- rad = 2.0*fsqrt(xpos*xpos+ypos*ypos);
- if(rad<1.0)
- val = 0.5+(cos(M_PI*rad)/2.0);
- else
- val = 0.0;
- return 1.3*val;
- }
-
- static freebrush(b)
- brush *b;
- {
- myfree(b->mat);
- myfree(b);
- }
-
- static int quant255(val)
- float val;
- {
- if (val<0.0)
- val = 0.0;
- if (val>1.0)
- val = 1.0;
- return (val*255.0)+0.50;
- }
-
- static float limit(val)
- float val;
- {
- if (val<0.0)
- return 0.0;
- if (val>1.0)
- return 1.0;
- return val;
- }
-
- static int noiseround(v)
- float v;
- {
- return ffloor(v+(0.99*(qrand()+0.5)));
- }
-
- static brush *makebrush(dx,dy,alpha)
- float dx, dy, alpha;
- {
- brush *b;
- int x, y;
- float hx, hy;
- unsigned char *cptr;
-
- b = (brush *)mymalloc(sizeof(brush));
- b->xsize = round(dx);
- if(b->xsize<1)
- b->xsize = 1;
- b->ysize = round(dy);
- if(b->ysize<1)
- b->ysize = 1;
- b->xorg = b->xsize/2;
- b->yorg = b->ysize/2;
- b->mat = (unsigned char *)mymalloc(b->xsize*b->ysize*sizeof(unsigned char));
- cptr = b->mat;
- hx = (b->xsize-1)/2.0;
- hy = (b->ysize-1)/2.0;
- alpha = 255.0*alpha;
- for(y=0; y<b->ysize; y++) {
- for(x=0; x<b->xsize; x++) {
- *cptr = noiseround(alpha*limit(brushfunc((x-hx)/b->xsize,(y-hy)/b->ysize)));
- cptr++;
- }
- }
- return b;
- }
-
- void drawbrush(dest,fx,fy)
- canvas *dest;
- float fx, fy;
- {
- int bxmin, bxmax;
- int bymin, bymax;
- int x, y;
- unsigned long *dptr;
- unsigned char *curc;
- rct brect;
- int ox, oy, nx;
- unsigned char *mat;
- brush *b;
-
- updatebrush(curwidth,can_curalpha*can_curalphascale);
- b = curbrush;
- if(!blendrow)
- setblend(BLEND_RGB);
- if(b->xsize&1)
- ox = round(fx-0.5);
- else
- ox = round(fx);
- if(b->ysize&1)
- oy = round(fy-0.5);
- else
- oy = round(fy);
- ox = ox-b->xorg;
- oy = oy-b->yorg;
- brect.xmin = ox;
- brect.xmax = ox+b->xsize-1;
- brect.ymin = oy;
- brect.ymax = oy+b->ysize-1;
- if (!rctinter(&dest->area,&brect,&brect))
- return;
- saverect(dest,&brect);
- nx = brect.xmax-brect.xmin+1;
- mat = b->mat+(brect.xmin-ox)+(brect.ymin-oy)*b->xsize;
- for(y=brect.ymin; y<=brect.ymax; y++) {
- blendrow(dest,mat,brect.xmin,y,nx,0);
- mat += b->xsize;
- }
- markdirty(dest,&brect,1);
- }
-
- /*
- * rand stuff follows
- *
- *
- */
- static initrand()
- {
- int i;
- float x, y, rad, sc;
-
- i = 0;
- circpos = (float *)mymalloc(2*RANDTABSIZE*sizeof(float));
- randtab = (float *)mymalloc(RANDTABSIZE*sizeof(float));
- while(i<RANDTABSIZE) {
- x = (frand()-0.5);
- y = (frand()-0.5);
- rad = fsqrt(x*x+y*y);
- if(rad <= 0.5) {
- sc = fsqrt(rad*2.0); /* warp to put more in center */
- circpos[2*i+0] = sc*x;
- circpos[2*i+1] = sc*y;
- i++;
- }
- }
- for(i=0; i<RANDTABSIZE; i++)
- randtab[i] = (frand()-0.5);
- }
-
- void getcircpos(x,y)
- float *x, *y;
- {
- int ind;
-
- if(!randfirsted) {
- initrand();
- randfirsted = 1;
- }
- qp++;
- if(qp == RANDTABSIZE)
- qp = 0;
- *x = circpos[2*qp+0];
- *y = circpos[2*qp+1];
- }
-
- float qrand()
- {
- if(!randtab)
- initrand();
- qp++;
- if(qp == RANDTABSIZE)
- qp = 0;
- return randtab[qp];
- }
-
-
- int getqrandstate()
- {
- return qp;
- }
-
- int setqrandstate(s)
- int s;
- {
- qp = s;
- }
-
- void setcurwidth(width)
- float width;
- {
- curwidth = width;
- }
-